﻿import com.crystalcentral.*;
import com.crystalcentral.model.*;
import com.crystalcentral.view.*;
import com.crystalcentral.util.*;

import mx.utils.Delegate;

import com.darronschall.DynamicRegistration;
import flash.geom.Point;
import flash.display.BitmapData;

import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.BevelFilter;

class com.crystalcentral.DiyTool
{
	private static var diyTool:DiyTool;

	static var HOST = "";
	

	var fontLoader:FontLoader;
	var diyInfoLoader:DiyInfoLoader;

	var diyInfo:DiyInfo;
	var mCanvas:MCanvas;
	var canvasCenter:Point;

	private var itemsToLoad:Number;

	var contextMenu:ContextMenu;

	private var keyListener:Object;
	
	
	/* color fill filters */
	var colorfill:Boolean = true;
	var noColorfillMatrix:Array;
    var noColorfillFilter:BitmapFilter;
	var bevelFilter:BevelFilter;
	
	private function DiyTool()
	{
		trace("DiyTool()");
		
		noColorfillMatrix = new Array();
   		noColorfillMatrix = noColorfillMatrix.concat([0, 0, 0, 0, 204]); // red
    	noColorfillMatrix = noColorfillMatrix.concat([0, 0, 0, 0, 204]); // green
    	noColorfillMatrix = noColorfillMatrix.concat([0, 0, 0, 0, 204]); // blue
    	noColorfillMatrix = noColorfillMatrix.concat([0, 0, 0, 1, 0]); // alpha
		noColorfillFilter = new ColorMatrixFilter(noColorfillMatrix);
		bevelFilter = new BevelFilter(1, 45, 0x666666, .8, 0xFFFFFF, .8, 0, 0, 1, 3, "inner", false);
	}

	public static function getInstance()
	{
		if (diyTool == null || diyTool == undefined)
		{
			diyTool = new DiyTool();
		}
		return diyTool;
	}

	function init()
	{
		trace("DiyTool:init();");
		if (_global.TEST_MODE)
		{
			HOST = "../httpdocs/";
		}
		this.itemsToLoad = 0;

		fontLoader = FontLoader.getInstance();
		diyInfoLoader = DiyInfoLoader.getInstance();
		mCanvas = new MCanvas();

		canvasCenter = new Point();
		canvasCenter.x = _root.canvasBackground._x + _root.canvasBackground._width / 2;
		canvasCenter.y = _root.canvasBackground._y + _root.canvasBackground._height / 2;

		loadFontList();

		initKeyActions();
	}

	// Step 1: Load Font List from XML
	function loadFontList()
	{
		trace("loadFontList()");
		this.startLoading("Loading Design Template...");
		fontLoader.loadFontList(HOST + "FontList.xml",loadDiyTemplate);
	}

	// Step 2: Load Diy Template from reedit.php
	function loadDiyTemplate()
	{
		this.startLoading("Loading Design Template...");
		fontLoader.initCbFontList(_root.cbFontList);

		trace(this + ":loadDiyTemplate()");
		var src;
		if (_global.TEST_MODE)
		{
			src = "diyInfo.xml";
		}
		else
		{
			src = _root.siteurl + "reedit.php?diytype=" + _root.diytype + "&typeid=" + _root.typeid + "&templatetype=" + _root.templatetype + "&gid=" + _root.gid + "&sampleid=" + _root.sampleid;
		}
		trace(src);
		diyInfoLoader.loadDiyInfo(src,initCanvas);
	}

	// Step 3: Init canvas, set product image as background
	function initCanvas()
	{
		trace("initCanvas()");
		diyTool.startLoading("Initializing Canvas...");
		mCanvas.loadProductBG(renderDiyInfo);
	}

	// Step 4: Render DIY Info
	function renderDiyInfo()
	{
		this.stopLoading();
		trace("renderDiyInfo()");

		DynamicRegistration.initialize(mCanvas.canvas);
		mCanvas.canvas.setRegistration(mCanvas.canvas._width / 2,mCanvas.canvas._height / 2);
		mCanvas.canvas._x2 = canvasCenter.x;
		mCanvas.canvas._y2 = canvasCenter.y;

		//_root.tips.text = "Version:"+String(diyInfo.version) + " " + String(diyInfo.version == 1);
		if (diyInfo.version == 1)
		{
			var scrollPos:Point = this.transformScrollPosition(new Point(diyInfo.scrollX, diyInfo.scrollY));
			_root.mcHScroll._x = scrollPos.x;
			_root.mcVScroll._y = scrollPos.y;
		}
		else
		{
			_root.mcHScroll._x = diyInfo.scrollX;
			_root.mcVScroll._y = diyInfo.scrollY;
		}
		this.scrollToH();
		this.scrollToV();

		this.zoomTo(diyInfo.zoomScale);

		for (var i = 0; i < diyInfo.items.length; i++)
		{
			switch (diyInfo.items[i].type)
			{
				case "text" :
					var diyTextItem:DiyTextItem = diyInfo.items[i];
					mCanvas.addTextItem(diyTextItem);

					//trace(diyTextItem);
					break;
				case "image" :
					var diyImageItem:DiyImageItem = diyInfo.items[i];
					mCanvas.addImageItem(diyImageItem);

					//trace(diyImageItem);
					break;
			}
		}

		initMouseActions();
	}

	function setTextTools(mText:MText)
	{
		trace("DiyTool:setTextTools()");
		_root.textTools.txtFontName.text = mText.diyTextItem.fontName;
		for (var i = 0; i < _root.textTools.cbFontList.length; i++)
		{
			var fname = String(_root.textTools.cbFontList.getItemAt(i).fname);
			if (fname == mText.diyTextItem.text)
			{
				_root.textTools.cbFontList.selectedIndex = i;
				return;
			}
		}
	}

	function onMouseDownAction()
	{
		//trace("onMouseDown(" + _xmouse + "," + _ymouse + ")");
		if (this.mCanvas.canvas.hitTest(_xmouse, _ymouse))
		{
			var mItem:MItem = this.mCanvas.currentItem;
			if (mItem == null || mItem == undefined)
			{
				return;
			}

			var ignoreList:Array = new Array(_root.global_toolbar, _root.mcHScroll, _root.mcVScroll);
			for (var i = 0; i < ignoreList.length; i++)
			{
				if (ignoreList[i].hitTest(_xmouse, _ymouse))
				{
					//trace(ignoreList[i] + " " + ignoreList[i].hitTest(_xmouse, _ymouse));
					//mItem.removeClickEvent();
					return;
				}
			}

			var objsCount = this.mCanvas.mItems.length;
			for (var i = 0; i < objsCount; i++)
			{
				var hit = this.mCanvas.mItems[i].mcItem.hitTest(_xmouse, _ymouse);
				//trace(this.mCanvas.mItems[i].mcItem + (hit ? " clicked" : " not clicked"));
				if (!hit)
				{
					this.mCanvas.mItems[i].setLostFocus();
				}
			}
		}
	}
	function onMouseUpAction()
	{

	}
	function initMouseActions()
	{
		// create a mouse listener object to detect mouse clicks
		var myMouseListener:Object = new Object();
		// define a function that executes when a user clicks the mouse
		myMouseListener.onMouseDown = Delegate.create(this, onMouseDownAction);
		myMouseListener.onMouseUp = Delegate.create(this, onMouseUpAction);
		// register the listener object with the Mouse object
		Mouse.addListener(myMouseListener);
	}

	public function get selectedObj()
	{
		return this.mCanvas.currentItem;
	}

	//finish to next step
	function getFinishVars()
	{
		var vars:LoadVars = new LoadVars();
		vars["productid"] = _root.productid;
		vars["diytype"] = _root.diytype;
		vars["typeid"] = _root.typeid;
		vars["historydiy"] = _root.historydiy;
		vars["productImageSrc"] = _root.productImageSrc;
		vars["comments"] = this.diyInfo.comments;
		vars["from"] = _root.from;
		vars["fromid"] = _root.fromid;
		vars["templatetype"] = _root.templatetype;
		vars["gid"] = _root.gid;
		vars["sampleid"] = _root.sampleid;
		vars["diyMaker"] = _root.diyMaker;

		// get all visible layers
		var iLen = this.mCanvas.mItems.length;
		var aLayerDepth = new Array();
		for (var i = 0; i < iLen; i++)
		{
			if (mCanvas.mItems[i].mcItem._visible)
			{
				var dep = aLayerDepth.length;
				aLayerDepth[dep] = {layer:Object, depth:Number};
				aLayerDepth[dep].layer = mCanvas.mItems[i];
				aLayerDepth[dep].depth = mCanvas.mItems[i].mcItem.getDepth();
			}
		}
		aLayerDepth.sortOn("depth",Array.DESCENDING | Array.NUMERIC);
		var count = aLayerDepth.length;
		trace("count=" + count);
		var bg = aLayerDepth[count - 1].layer;
		for (var i = 0; i < count; i++)
		{
			var mcItem = aLayerDepth[i].layer;
			var diyItem = aLayerDepth[i].layer.diyItem;

			vars["object" + i + "type"] = diyItem.type;
			vars["object" + i + "x"] = mcItem.mcItem._x;
			vars["object" + i + "y"] = mcItem.mcItem._y;
			vars["object" + i + "w"] = mcItem.mcContent._width;
			vars["object" + i + "h"] = mcItem.mcContent._height;
			vars["object" + i + "rotation"] = mcItem.mcItem._rotation;
			vars["object" + i + "xs"] = mcItem.mcContent._xscale;
			vars["object" + i + "ys"] = mcItem.mcContent._yscale;

			if (diyItem.type == "text")
			{
				vars["object" + i + "text"] = diyItem.text;
				vars["object" + i + "font"] = diyItem.fontName;
				vars["object" + i + "size"] = diyItem.fontSize;
				vars["object" + i + "bold"] = diyItem.bold;
				vars["object" + i + "italic"] = diyItem.italic;
				vars["object" + i + "underline"] = diyItem.underline;
				vars["object" + i + "align"] = diyItem.align;
				vars["object" + i + "color"] = diyItem.color;
				vars["object" + i + "letterSpacing"] = diyItem.letterSpacing;
				vars["object" + i + "leading"] = diyItem.leading;
				vars["object" + i + "wordWrap"] = mcItem.tf.wordWrap;
			}
			else
			{
				vars["object" + i + "src"] = diyItem.src;
			}
		}
		vars["objCount"] = count;

		//send zoomBar pos and H/V scrollBar pos
		vars["zoomScale"] = diyInfo.zoomScale;
		vars["scrollX"] = diyInfo.scrollX;
		vars["scrollY"] = diyInfo.scrollY;
		vars["version"] = 2;

		return vars;
	}

	function finish()
	{
		this.startLoading("Processing...");
		var vars:LoadVars = getFinishVars();
		if (_root.diyMaker == "yes")
		{
			vars.send(_root.siteurl + "step3_maker.php","_self","POST");
		}
		else
		{
			vars.send(_root.siteurl + "step3.php","_self","POST");
		}
	}

	function finish_show()
	{
		this.startLoading("Processing...");

		if (_root.diyMaker == "yes")
		{
			sendDataDiyMaker();
			return;
		}

		mCanvas.setAllLostFocus();
		var who = mCanvas.canvas;
		who.setMask(null);
		var snap = new BitmapData(who._width / who._xscale * 100, who._height / who._yscale * 100);
		snap.draw(who);
		who.setMask(_root.mCanvasMask);
		/*
		var mcSnap = _root.createEmptyMovieClip("mcSnap", _root.getNextHighestDepth());
		mcSnap._x = 0; mcSnap._y = 0;
		mcSnap.attachBitmap(snap, mcSnap.getNextHighestDepth());
		mcSnap.onPress = function() {this._visible = false;}
		return;
		*/
		var pixels:Array = new Array();
		var tmp;
		var w:Number = snap.width;
		var h:Number = snap.height;
		//Build pixels array using an onEnterframe to avoid timeouts, capture a row per iteration, show a progressbar
		var cnt:Number = 0;
		var step:Number = 50;
		var perc;
		var a:Number;
		who.onEnterFrame = function()
		{
			for (a = cnt; a < cnt + step && a <= w; a++)
			{
				for (var b = 0; b <= h; b++)
				{
					//tmp = snap.getPixel32(a, b).toString(16);
					//pixels.push(tmp.substr(1));
					tmp = snap.getPixel32(a, b);
					pixels.push(tmp);
				}
				perc = int((a * 100) / w);
				_root.mcLoading.loadingPercent(perc,"Generating Design Image...");
			}

			cnt += step;
			if (a > w)
			{
				_root.diyTool.stopLoading();
				//Finish capturing
				_root.diyTool.sendData(pixels,h,w);
				//free memory
				snap.dispose();
				delete who.onEnterFrame;
			}
			//}  
		};
	}

	function sendDataDiyMaker()
	{
		var send_lv:LoadVars = getFinishVars();
		send_lv.version = 2;
		//The page (and this movie itself) should be in a server to work
		this.startLoading("Sending DIY-Maker Template to Server");
		send_lv.send(_root.siteurl + "step3_maker.php","_self","POST");
	}

	function sendData(pixels:Array, h:Number, w:Number)
	{
		trace("sendData");
		var result_lv:LoadVars = new LoadVars();
		result_lv.onLoad = function(success:Boolean)
		{
			if (success)
			{
				_root.tips.autoSize = true;
				_root.tips.text = result_lv.imageFile;
				_root.tips.text += newline + unescape(result_lv.redirectURL);
				getURL(unescape(result_lv.redirectURL), "_self");
			}
			else
			{
				_root.tips.text = "Error connecting to server.";
			}
			//_root.diyTool.stopLoading();
		};

		//Create the LoadVars object and pass data to PHP script
		var send_lv:LoadVars = getFinishVars();
		//output.img = pixels.toString();
		send_lv.img = pixels;
		send_lv.height = h;
		send_lv.width = w;
		send_lv.version = 2;
		//The page (and this movie itself) should be in a server to work
		this.startLoading("Sending Image to Server");
		send_lv.sendAndLoad(_root.siteurl + "step3.php",result_lv,"POST");
		//send_lv.send(_root.siteurl + "step3.php", "_blank", "POST");
	}
	
	function zoomTo(zscale:Number)
	{
		if (zscale < 50)
		{
			zscale = 50;
		}
		if (zscale > 200)
		{
			zscale = 200;
		}

		if (Math.abs(100 - zscale) < 2)
		{
			zscale = 100;
		}

		diyInfo.zoomScale = zscale;
		mCanvas.canvas._xscale2 = diyInfo.zoomScale;
		mCanvas.canvas._yscale2 = diyInfo.zoomScale;
		_root.mcZoom.zoomTrackPoint.moveToZoomPos(zscale);
		scrollToH();
		scrollToV();
	}
	function scrollToH()
	{
		var min = _root.scrollHTrack._x;
		var max = _root.scrollHTrack._x + _root.scrollHTrack._width - _root.mcHScroll._width;
		var base = (min + max) / 2;
		var trackWidth = max - min;
		var scale = _root.canvasBackground._width / Math.abs(max - min);
		//mCanvas.canvas._x = (base - _root.mcHScroll._x) * scale + _global.canvasCrossX - _global.canvasWidth * diyInfo.zoomScale / 100 / 2;
		mCanvas.canvas._x = (base - _root.mcHScroll._x) / trackWidth * mCanvas.canvas._width + _global.canvasCrossX -  mCanvas.canvas._width / 2;
		diyInfo.scrollX = _root.mcHScroll._x;
	}
	function scrollToV()
	{
		var min = _root.scrollVTrack._y;
		var max = _root.scrollVTrack._y + _root.scrollVTrack._height - _root.mcVScroll._height;
		var base = (min + max) / 2;
		var trackHeight = max - min;
		var scale = _root.canvasBackground._height / Math.abs(max - min);
		//mCanvas.canvas._y = (base - _root.mcVScroll._y) * scale + _global.canvasCrossY - _global.canvasHeight * diyInfo.zoomScale / 100 / 2;
		mCanvas.canvas._y = (base - _root.mcVScroll._y) / trackHeight * mCanvas.canvas._height + _global.canvasCrossY -  mCanvas.canvas._height / 2;
		diyInfo.scrollY = _root.mcVScroll._y;
	}
	private function transformScrollPosition(pos:Point)
	{
		trace("Scroll Position V1: (" + pos.x + "," + pos.y + ")");
		var oldVTrackY = 115.2;
		var oldVTrackHeight = 506;
		var oldVBarHeight = 54;
		var oldHTrackX = 37;
		var oldHTrackWidth = 666;
		var oldHBarWidth = 54;

		var newVTrackY = _root.scrollVTrack._y;
		var newVTrackHeight = _root.scrollVTrack._height;
		var newVBarHeight = _root.mcVScroll._height;
		var newHTrackX = _root.scrollHTrack._x;
		var newHTrackWidth = _root.scrollHTrack._width;
		var newHBarWidth = _root.mcHScroll._width;

		var newPos:Point = new Point();
		newPos.x = (pos.x - oldHTrackX) / (oldHTrackWidth - oldHBarWidth) * (newHTrackWidth - newHBarWidth) + newHTrackX;
		newPos.y = (pos.y - oldVTrackY) / (oldVTrackHeight - oldVBarHeight) * (newVTrackHeight - newVBarHeight) + newVTrackY;

		trace("Scroll Position V2: (" + newPos.x + "," + newPos.y + ")");

		return newPos;
	}

	function startLoading(info:String)
	{
		//if (itemsToLoad == 0) {
		_root.mcLoading.loadingUnknown(true,info);
		//}
		itemsToLoad++;
		//trace("startLoading: " + itemsToLoad);
	}
	function stopLoading()
	{
		itemsToLoad--;
		//trace("stopLoading: " + itemsToLoad);

		if (itemsToLoad == 0)
		{
			_root.mcLoading.stopLoading();
		}
	}

	function getContextMenu()
	{
		if (this.contextMenu == undefined)
		{
			this.contextMenu = new ContextMenu();
			this.contextMenu.hideBuiltInItems();
			this.contextMenu.customItems.push(new ContextMenuItem("Bring to Front", bringToFront));
			this.contextMenu.customItems.push(new ContextMenuItem("Send to Back", sendToBack));
		}

		return this.contextMenu;
	}
	function bringToFront(obj, item)
	{
		trace(_root.diyTool.selectedObj);
		_root.diyTool.selectedObj.bringToFront();
	}
	function sendToBack(obj, item)
	{
		_root.diyTool.selectedObj.sendToBack();
	}

	function initKeyActions()
	{
		trace("DiyTool:initKeyActions();");
		keyListener = new Object();
		keyListener.onKeyDown = function()
		{
			var key = Key.getCode();
			//trace("Key down - code: " + key);
			var MOVE_UNIT = 5 * 100 / _root.diyTool.diyInfo.zoomScale;
			switch (key)
			{
				case Key.UP :
					trace("Key.UP");
					with (_root.diyTool.selectedObj)
					{
						moveTo(mcItem._x, mcItem._y - MOVE_UNIT);
					}
					break;
				case Key.DOWN :
					trace("Key.DOWN");
					with (_root.diyTool.selectedObj)
					{
						moveTo(mcItem._x, mcItem._y + MOVE_UNIT);
					}
					break;
				case Key.LEFT :
					trace("Key.LEFT");
					with (_root.diyTool.selectedObj)
					{
						moveTo(mcItem._x - MOVE_UNIT, mcItem._y);
					}
					break;
				case Key.RIGHT :
					trace("Key.RIGHT");
					with (_root.diyTool.selectedObj)
					{
						moveTo(mcItem._x + MOVE_UNIT, mcItem._y);
					}
					break;
				case Key.DELETEKEY :
					trace("Key.DELETEKEY");
					if (!(_root.diyTool.selectedObj.diyItem.type == "text" && _root.diyTool.selectedObj.editable))
						_root.diyTool.selectedObj.remove();
					break;
				case Key.CONTROL :
					trace("Key.CONTROL");
					_global.ctrl = true;
					break;
				case 90 :// z
					trace("Key.z");
					if (_global.ctrl == true)
					{
						if (!(_root.diyTool.selectedObj.diyItem.type == "text" && _root.diyTool.selectedObj.editable))
							_root.undo();
					}
					break;
				case 89 :// y
					trace("Key.y");
					if (_global.ctrl == true)
					{
						if (!(_root.diyTool.selectedObj.diyItem.type == "text" && _root.diyTool.selectedObj.editable))
							_root.redo();
					}
					break;
				case 219 :// [
					trace("Key.[");
					if (_global.ctrl == true)
					{
						_root.diyTool.selectedObj.sendToBack();
					}
					break;
				case 221 :// ]
					trace("Key.]");
					if (_global.ctrl == true)
					{
						_root.diyTool.selectedObj.bringToFront();
					}
					break;
				default :
					trace("Key down - code: " + key);
			}
		};
		keyListener.onKeyUp = function()
		{
			var key = Key.getCode();
			//trace("Key up - code: " + key);
			switch (key)
			{
				case Key.CONTROL :
					_global.ctrl = false;
					break;
				default :
					break;
			}
		};
		Key.addListener(keyListener);
	}
	
	function setColorfill(isColorfill:Boolean) {
		this.colorfill = isColorfill;
		trace(this.colorfill);
		
		var mItems:Array = mCanvas.mItems;
		for (var i=0; i<mItems.length; i++) {
			mItems[i].setColorfill(this.colorfill)
		}
	}
}